package synchronize;

import java.time.LocalDateTime;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * @author bc
 * @Description:
 * @date 2024/03/20
 */
@SuppressWarnings("ALL")
public class SynchronizationTestDemo {

    private static String staticVariable = "bc";

    private String commonVariable = "bcc";

    public static void main(String[] args) {
        SynchronizationTestDemo testDemo = new SynchronizationTestDemo();
        //方法上锁
//        testDemo.test1();

        //变量上锁
//        testDemo.test2();

        //this 和 class
        testDemo.test3();
    }

    private static synchronized void staticMethod() {
        System.out.println("执行静态方法" + LocalDateTime.now());
        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
    }

    private synchronized void commonMethod() {
        System.out.println("执行普通方法" + LocalDateTime.now());
        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
    }

    private static void staticMethodValue() {
        synchronized (staticVariable) {
            System.out.println("执行静态方法" + LocalDateTime.now());
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }
    }

    private void commonMethodValue() {
        synchronized (commonVariable) {
            System.out.println("执行普通方法" + LocalDateTime.now());
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }
    }

    private static void classMethod() {
        synchronized (SynchronizationTestDemo.class) {
            System.out.println("class方法" + LocalDateTime.now());
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }
    }

    private void thisMethod() {
        synchronized (this) {
            System.out.println("this方法" + LocalDateTime.now());
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }
    }

    private void test1() {
        ExecutorService threadPool = Executors.newFixedThreadPool(10);

        threadPool.execute(() -> {
            staticMethod();
        });

        threadPool.execute(() -> {
            staticMethod();
        });

        SynchronizationTestDemo demo1 = new SynchronizationTestDemo();
        threadPool.execute(() -> {
            demo1.commonMethod();
        });

        //普通方法同对象会阻塞
        threadPool.execute(() -> {
            demo1.commonMethod();
        });

        //普通方法不同对象不会阻塞
        SynchronizationTestDemo demo2 = new SynchronizationTestDemo();
        threadPool.execute(() -> {
            demo2.commonMethod();
        });
    }

    private void test2() {
        ExecutorService threadPool = Executors.newFixedThreadPool(10);

        threadPool.execute(() -> {
            staticMethodValue();
        });

        threadPool.execute(() -> {
            staticMethodValue();
        });

        SynchronizationTestDemo demo1 = new SynchronizationTestDemo();
        threadPool.execute(() -> {
            demo1.commonMethodValue();
        });

        //普通方法同对象会阻塞
        threadPool.execute(() -> {
            demo1.commonMethodValue();
        });

        //普通方法不同对象不会阻塞
        SynchronizationTestDemo demo2 = new SynchronizationTestDemo();
        threadPool.execute(() -> {
            demo2.commonMethodValue();
        });
    }

    private void test3() {
        ExecutorService threadPool = Executors.newFixedThreadPool(10);

        threadPool.execute(() -> {
            SynchronizationTestDemo demo1 = new SynchronizationTestDemo();
            demo1.thisMethod();
        });

        threadPool.execute(() -> {
            SynchronizationTestDemo demo2 = new SynchronizationTestDemo();
            demo2.thisMethod();
        });

        threadPool.execute(() -> {
            SynchronizationTestDemo demo3 = new SynchronizationTestDemo();
            demo3.classMethod();
        });

        threadPool.execute(() -> {
            SynchronizationTestDemo demo4 = new SynchronizationTestDemo();
            demo4.classMethod();
        });


    }
}
